#pragma once
#include <iostream>
#include <functional>
#include <sys/epoll.h>
#include <unistd.h>
#include <memory>
class Poller;//Pooler类的声明
class EventLoop;//EventLoop类的声明
using EventCallback = std::function<void()>;
//Channel模块是对⼀个描述符需要进行的IO事件管理的模块，实现对描述符可读，可写，错误事件的管理操作，
//以及Poller模块对文件描述符进行IO事件监控就绪后，根据不同的事件，回调不同的处理函数。
class Channel
{
public:
    Channel(EventLoop* loop, int fd)
        :_loop(loop)
        ,_fd(fd)
        ,_events(0)
        ,_revents(0)
    {}
public:
    //fd的偷家函数
    int GetFd() {return _fd;}
    //_events的偷家函数，获取想要监控的事件
    uint32_t Events() { return _events;}
    //设置实际触发的事件
    void SetREvents(uint32_t events) { _revents = events; }
    //设置可读事件的回调
    void SetReadCallback(const EventCallback &callback)  { _readCallback  = callback; }
    //设置可写事件的回调
    void SetWriteCallback(const EventCallback &callback) { _writeCallback = callback; }
    //设置错误事件的回调
    void SetErrorCallback(const EventCallback &callback) { _errorCallback = callback; }
    //设置连接断开事件的回调
    void SetCloseCallback(const EventCallback &callback) { _closeCallback = callback; }
    //设置任意事件的回调
    void SetEventCallback(const EventCallback &callback) { _eventCallback = callback; }
    //判断当前是否监控了可读
    bool ReadAble() { return _events & EPOLLIN; }
    //判断当前是否监控了可写
    bool WriteAble() { return _events & EPOLLOUT; }
    //启动读事件监控
    void EnableRead() { _events |= EPOLLIN; Update(); }
    //启动写事件监控
    void EnableWrite() { _events |= EPOLLOUT; Update(); }
    //关闭可读事件监控
    void DisableRead() { _events &= ~EPOLLIN; Update(); }
    //关闭可写事件监控
    void DisableWrite() { _events &= ~EPOLLOUT; Update(); }
    //关闭所有事件监控
    void DisableAll() { _events = 0; Update();}
    //移除监控（从epoll红黑树中进行移除）
    void Remove();//这里是声明，定义在EventLoop.hpp尾部
    //添加或修改监控
    void Update();//这里是声明，定义在EventLoop.hpp尾部
    //事件处理，一旦连接触发了事件，就调用这个函数，自己触发什么事件如何处理由自己决定，通过_revents判断触发了什么事件
    void HandleEvent()
    {
        if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))//可读事件、对方关闭连接、发生紧急数据可读事件，通常用于带外数据或非标准数据的通知。就绪
        {
            if (_eventCallback) { _eventCallback(); }//不管任何事件都去调用的回调函数，例如刷新任务，防止读写超时
            if (_readCallback) { _readCallback(); }
        }
        //有可能会释放连接的操作一次只处理一个
        if (_revents & EPOLLOUT)//可写事件就绪
        {
            if (_eventCallback) { _eventCallback(); }//不管任何事件都去调用的回调函数，例如刷新任务，防止读写超时
            if (_writeCallback) { _writeCallback(); }
        }
        else if (_revents & EPOLLERR)//错误事件就绪，准备释放连接 
        {
            if (_eventCallback) { _eventCallback(); }//不管任何事件都去调用的回调函数，例如刷新任务，防止读写超时
            if (_errorCallback) { _errorCallback(); }
        }
        else if (_revents & EPOLLHUP)//套接字挂起事件就绪，连接的对端关闭了连接或者发生了一些异常情况。 
        {
            if (_eventCallback) { _eventCallback(); }//不管任何事件都去调用的回调函数，例如刷新任务，防止读写超时
            if (_closeCallback) { _closeCallback(); }
        } 
        /*if (_event_callback) _event_callback();*/
    }
private:    
    int _fd;//被监控的文件描述符
    EventLoop* _loop;//EventLoop类
    uint32_t _events;//当前需要监控的事件
    uint32_t _revents;//当前连接触发的事件
    EventCallback _readCallback;//可读事件被触发的回调函数
    EventCallback _writeCallback;//可写事件被触发的回调函数
    EventCallback _errorCallback;//错误事件被触发的回调函数
    EventCallback _closeCallback;//连接断开事件被触发的回调函数
    EventCallback _eventCallback;//任意事件被触发的回调函数
};
